/*
 * UMediaFrame.cpp
 *
 *  Created on: 2020年7月11日
 *      Author: terry
 */

#include "UMediaFrame.h"
#include "Ffmpeg.h"
#include <utility>

UMediaFrame::UMediaFrame(AVFrame* frame, bool refIt):
        m_avframe(frame),
        m_own(refIt)
{
}

UMediaFrame::~UMediaFrame()
{
    cleanup();
}

void UMediaFrame::cleanup()
{
    if (m_own)
    {
        av_frame_free(&m_avframe);
        m_own = false;
    }
    else
    {
        m_avframe = NULL;
    }
}

UMediaFrame::UMediaFrame(const UMediaFrame& frame):
    m_avframe(),
    m_own()
{
    ref(frame.get());
}

UMediaFrame& UMediaFrame::operator = (const UMediaFrame& frame)
{
    ref(frame.get());

    return *this;
}


AVFrame* UMediaFrame::get()
{
    return m_avframe;
}

const AVFrame* UMediaFrame::get() const
{
	return m_avframe;
}


uint8_t ** UMediaFrame::data()
{
    return m_avframe->data;
}

uint8_t * UMediaFrame::data(size_t idx)
{
    return m_avframe->data[idx];
}

int* UMediaFrame::linesize()
{
    return m_avframe->linesize;
}

int& UMediaFrame::linesize(size_t idx)
{
    return m_avframe->linesize[idx];
}

void UMediaFrame::linesize(size_t idx, int size)
{
    m_avframe->linesize[idx] = size;
}




int UMediaFrame::width() const
{
    return m_avframe->width;
}

int UMediaFrame::height() const
{
    return m_avframe->height;
}

int UMediaFrame::nb_samples() const
{
    return m_avframe->nb_samples;
}

int UMediaFrame::format() const
{
    return m_avframe->format;
}

int UMediaFrame::key_frame() const
{
    return m_avframe->key_frame;
}

int UMediaFrame::pict_type() const
{
    return m_avframe->pict_type;
}

int64_t UMediaFrame::pts() const
{
    return m_avframe->pts;
}

int64_t UMediaFrame::pkt_pts() const
{
    return m_avframe->pkt_pts;
}

void *UMediaFrame::opaque() const
{
    return m_avframe->opaque;
}

int UMediaFrame::flags() const
{
    return m_avframe->flags;
}

void UMediaFrame::set_width(int val)
{
    m_avframe->width = val;
}

void UMediaFrame::set_height(int val)
{
    m_avframe->height = val;
}

void UMediaFrame::set_nb_samples(int val)
{
    m_avframe->nb_samples = val;
}

void UMediaFrame::set_format(int val)
{
    m_avframe->format = val;
}

void UMediaFrame::set_key_frame(int val)
{
    m_avframe->key_frame = val;
}

void UMediaFrame::set_pict_type(int val)
{
    m_avframe->pict_type = (AVPictureType)val;
}


void UMediaFrame::set_pts(int64_t val)
{
    m_avframe->pts = val;
}

void UMediaFrame::set_pkt_pts(int64_t val)
{
    m_avframe->pkt_pts = val;
}

void UMediaFrame::set_opaque(void* val)
{
    m_avframe->opaque = val;
}

void UMediaFrame::set_flags(int val)
{
    m_avframe->flags = val;
}




int UMediaFrame::channels() const
{
    return get_channels();
}

int UMediaFrame::sample_rate() const
{
    return get_sample_rate();
}

int64_t UMediaFrame::channel_layout() const
{
    return get_channel_layout();
}


int64_t UMediaFrame::get_best_effort_timestamp() const
{
    return av_frame_get_best_effort_timestamp(m_avframe);
}

void    UMediaFrame::set_best_effort_timestamp(int64_t val)
{
    av_frame_set_best_effort_timestamp(m_avframe, val);
}

int64_t UMediaFrame::get_pkt_duration         () const
{
    return av_frame_get_pkt_duration(m_avframe);
}

void    UMediaFrame::set_pkt_duration         (int64_t val)
{
    av_frame_set_pkt_duration(m_avframe, val);
}

int64_t UMediaFrame::get_pkt_pos              () const
{
    return av_frame_get_pkt_pos(m_avframe);
}

void    UMediaFrame::set_pkt_pos              (int64_t val)
{
    av_frame_set_pkt_pos(m_avframe, val);
}

int64_t UMediaFrame::get_channel_layout       () const
{
    return av_frame_get_channel_layout(m_avframe);
}

void    UMediaFrame::set_channel_layout       (int64_t val)
{
    av_frame_set_channel_layout(m_avframe, val);
}

int     UMediaFrame::get_channels             () const
{
    return av_frame_get_channels(m_avframe);
}

void    UMediaFrame::set_channels             (int     val)
{
    av_frame_set_channels(m_avframe, val);
}

int     UMediaFrame::get_sample_rate          () const
{
    return av_frame_get_sample_rate(m_avframe);
}

void    UMediaFrame::set_sample_rate          (int     val)
{
    av_frame_set_sample_rate(m_avframe, val);
}


int     UMediaFrame::get_decode_error_flags   () const
{
    return av_frame_get_decode_error_flags(m_avframe);
}

void    UMediaFrame::set_decode_error_flags   (int     val)
{
    av_frame_set_decode_error_flags(m_avframe, val);
}

int     UMediaFrame::get_pkt_size() const
{
    return av_frame_get_pkt_size(m_avframe);
}

void    UMediaFrame::set_pkt_size(int val)
{
    av_frame_set_pkt_size(m_avframe, val);
}


int UMediaFrame::get_buffer(int align)
{
    return av_frame_get_buffer(m_avframe, align);
}

bool UMediaFrame::is_writable() const
{
    return av_frame_is_writable(m_avframe) > 0;
}

int UMediaFrame::make_writable()
{
    return av_frame_make_writable(m_avframe);
}

int UMediaFrame::copy(AVFrame* src)
{
    return av_frame_copy(m_avframe, src);
}

int UMediaFrame::copy_props(AVFrame* src)
{
    return av_frame_copy_props(m_avframe, src);
}

void UMediaFrame::reset()
{
    cleanup();
}

UMediaFrame& UMediaFrame::clone(AVFrame* src)
{
    cleanup();

    m_avframe = av_frame_clone(src);
    m_own = true;

    return *this;
}

void UMediaFrame::swap(UMediaFrame& other)
{
    std::swap(m_avframe, other.m_avframe);
    std::swap(m_own, other.m_own);
}

bool UMediaFrame::create()
{
    cleanup();

    m_avframe = av_frame_alloc();
    m_own = true;

    return (m_avframe != nullptr);
}

bool UMediaFrame::ref(const AVFrame* src)
{
	cleanup();

    m_avframe = av_frame_alloc();
    m_own = true;

    if (src == nullptr)
    {
        return false;
    }

    int ret = av_frame_ref(m_avframe, src);
    return ret == 0;
}

bool UMediaFrame::ref(const UMediaFrame& src)
{
    return ref(src.get());
}

bool UMediaFrame::isVideo() const
{
	return width() != 0;
}
